/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef _MACHINE_CTRL_CLIENT_HPP
#define _MACHINE_CTRL_CLIENT_HPP

#include "MaCIClients.hpp"
#include "MachineCtrlTypes.hpp"
#include "MaCICtrlClient.hpp"

namespace MaCI{
  namespace MachineCtrl{
    class CMachineCtrlClient{
    public:
      
      /** Constructor
       *
       * Constructor for CMachineCtrlClient. GIMI pointer will be used for searching services and 
       * is also passed to the client of the machine for communication.
       *
       * Constructor makes a service discovery and creates clients for every services that is 
       * under given MaCI-group.
       *
       * @param[in] aGIMIPtr       GIMI pointer which will be passed to the clients
       * @param[in] aMaCIGroup     MaCIGroup name of the machine
       */
      CMachineCtrlClient(gimi::GIMI *aGIMIPtr,std::string aMaCIGroup);

      /** Constructor
       *
       * Constructor which creates its own GIMI instance.
       *
       * Constructor makes a service discovery and creates clients for every services that is 
       * under given MaCI-group.
       *
       * @param[in] aGIMnetAPAddress  Address of GIMnet AP to connect
       * @param[in] aGIMnetAPPort     Port of GIMnet AP to connect
       * @param[in] aGIMnetName       name of the GIMnet instance
       * @param[in] aMaCIGroup        MaCI-group of the machine
       */
      CMachineCtrlClient(std::string aGIMnetAPAddress,
                         unsigned int aGIMnetAPPort,
                         std::string aGIMnetName,
                         std::string aMaCIGroup);

      /**
       * Destructor
       */
      ~CMachineCtrlClient();
      
      /**
       * Open all clients of wanted type. It is also possible to open them all.
       *
       * @param[in] aType       Type of the clients, All types as a default value            
       * @return                true if every clients succesfully opened, otherwise false.
       */
      bool OpenClients(const EInterfaceType &aType = KTypeAll);

      /**
       * Close all clients of wanted type. It is also possible to open them all.
       *
       * @param[in] aType       Type of the clients, All types as a default value            
       * @return                true if every clients succesfully closed, otherwise false.
       */   
      bool CloseClients(const EInterfaceType &aType = KTypeAll);

     
      /**
       * Update the state of the machine by doing service discovery on the network, and adding
       * new services belonging to the machine 
       */
      void Update();
 
      /**
       * Get the components of the machine. 
       * Returns a list which contains the names of machine clients.
       *
       * @param[out] aComponents  A list of components
       */
      void GetMachineComponents(TMaCIMachineComponents &aComponents);

      //**********************************************
      //**********************************************
      //GETTERS FOR ALL THE CLIENT TYPES BELOW
      //**********************************************
      //**********************************************

      //***********************************
      //**************ALARM****************
      //***********************************
      /**
       * Get All Alarm clients of a machine
       *
       * \see AlarmClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to TAlarmClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TAlarmClientMap GetAlarmClients(bool aOpen = false);
      
      /**
       * Get one Alarm client of a machine by giving the instance name
       *
       * \see AlarmClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Behaviour client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Alarm::CAlarmClient *GetAlarmClient(std::string aInstanceName, bool aOpen = false);


      //***********************************
      //**********BEHAVIOUR****************
      //***********************************
      /**
       * Get All Behaviour clients of a machine
       *
       * \see BehaviourClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TBehaviourClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TBehaviourClientMap GetBehaviourClients(bool aOpen = false);
      
      /**
       * Get one Behaviour client of a machine by giving the instance name
       *
       * \see BehaviourClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Behaviour client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Behaviour::CBehaviourClient *GetBehaviourClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********COORDINATE DRIVE*********
      //***********************************
      /**
       * Get All CoordinateDrive clients of a machine
       *
       * \see CoordinateDriveClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TCoordinateDriveClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TCoordinateDriveClientMap GetCoordinateDriveClients(bool aOpen = false);

      /**
       * Get one CoordinateDrive client of a machine by giving the instance name
       *
       * \see CoordinateDriveClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the CoordinateDrive client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::CoordinateDrive::CCoordinateDriveClient *GetCoordinateDriveClient(std::string aInstanceName, bool aOpen = false);
      

      //***********************************
      //**********EMERGENCY STOP***********
      //***********************************
      /**
       * Get All EmergencyStop clients of a machine
       *
       * \see EmergencyStopClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TEmergencyStopClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TEmergencyStopClientMap GetEmergencyStopClients(bool aOpen = false);

      /**
       * Get one EmergencyStop client of a machine by giving the instance name
       *
       * \see EmergencyStopClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the EmergencyStop client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::EmergencyStop::CEmergencyStopClient *GetEmergencyStopClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********ENERGY*******************
      //***********************************

      /**
       * Get All Energy clients of a machine
       *
       * \see EnergyClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TEnergyClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TEnergyClientMap GetEnergyClients(bool aOpen = false);
     
      /**
       * Get one Energy client of a machine by giving the instance name
       *
       * \see EnergyClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Energy client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Energy::CEnergyClient *GetEnergyClient(std::string aInstanceName, bool aOpen = false);


      //***********************************
      //**********IMAGE********************
      //***********************************
      /**
       * Get All Image clients of a machine
       *
       * \see ImageClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TImageClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TImageClientMap GetImageClients(bool aOpen = false);

      /**
       * Get one Image client of a machine by giving the instance name
       *
       * \see ImageClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Image client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Image::CImageClient *GetImageClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********IMU**********************
      //***********************************
      /**
       * Get All IMU clients of a machine
       *
       * \see IMUClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TIMUClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TIMUClientMap GetIMUClients(bool aOpen = false);

      /**
       * Get one IMU client of a machine by giving the instance name
       *
       * \see IMUClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the IMU client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::IMU::CIMUClient *GetIMUClient(std::string aInstanceName, bool aOpen = false);
      

      //***********************************
      //**********IO***********************
      //***********************************
      /**
       * Get All IO clients of a machine
       *
       * \see IOClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TIOClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TIOClientMap GetIOClients(bool aOpen = false);

      /**
       * Get one IO client of a machine by giving the instance name
       *
       * \see IOClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the IO client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::IO::CIOClient *GetIOClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********JOINTGROUPCTRL***********
      //***********************************
      /**
       * Get All JointGroupCtrl clients of a machine
       *
       * \see JointGroupCtrlClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TJointGroupCtrlClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TJointGroupCtrlClientMap GetJointGroupCtrlClients(bool aOpen = false);

      /**
       * Get one JointGroupCtrl client of a machine by giving the instance name
       *
       * \see JointGroupCtrlOClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the JointGroupCtrl client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::JointGroupCtrl::CJointGroupCtrlClient *GetJointGroupCtrlClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********MAP**********************
      //***********************************
      /**
       * Get All Map clients of a machine
       *
       * \see MapClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TMapClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TMapClientMap  GetMapClients(bool aOpen = false);


      /**
       * Get one Map client of a machine by giving the instance name
       *
       * \see MapClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Map client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Map::CMapClient *GetMapClient(std::string aInstanceName, bool aOpen = false);
      
      //***********************************
      //**********PARAMETER****************
      //***********************************
      /**
       * Get All Parameter clients of a machine
       *
       * \see ParameterClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TParameterClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TParameterClientMap  GetParameterClients(bool aOpen = false);

      /**
       * Get one Parameter client of a machine by giving the instance name
       *
       * \see ParameterClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Parameter client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Parameter::CParameterClient *GetParameterClient(std::string aInstanceName, bool aOpen = false);
   
      //***********************************
      //**********POSITION*****************
      //***********************************
      /**
       * Get All Position clients of a machine
       *
       * \see PositionClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TPositionClientMap which contains all 
       *                               the pointers and instance names of the machine
       */ 
      TPositionClientMap GetPositionClients(bool aOpen = false);


      /**
       * Get one Position client of a machine by giving the instance name
       *
       * \see PositionClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Position client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Position::CPositionClient *GetPositionClient(std::string aInstanceName, bool aOpen = false);
     
      //***********************************
      //**********RANGING******************
      //***********************************
      /**
       * Get All Ranging clients of a machine
       *
       * \see RangingClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TRangingClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TRangingClientMap GetRangingClients(bool aOpen = false);


      /**
       * Get one Ranging client of a machine by giving the instance name
       *
       * \see RangingClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Ranging client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Ranging::CRangingClient *GetRangingClient(std::string aInstanceName, bool aOpen = false);
     
      //***********************************
      //**********SPEEDCTRL****************
      //***********************************
      /**
       * Get All SpeedCtrl clients of a machine
       *
       * \see SpeedCtrlClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TSpeedCtrlClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TSpeedCtrlClientMap GetSpeedCtrlClients(bool aOpen = false);


      /**
       * Get one SpeedCtrl client of a machine by giving the instance name
       *
       * \see SpeedCtrlClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the SpeedCtrl client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::SpeedCtrl::CSpeedCtrlClient *GetSpeedCtrlClient(std::string aInstanceName, bool aOpen = false);

      //***********************************
      //**********TEXT*********************
      //***********************************
      /**
       * Get All Text clients of a machine
       *
       * \see TextClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TTextClientMap which contains all 
       *                               the pointers and instance names of the machine
       */  
      TTextClientMap GetTextClients(bool aOpen = false);


      /**
       * Get one Text client of a machine by giving the instance name
       *
       * \see TextClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Text client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Text::CTextClient *GetTextClient(std::string aInstanceName, bool aOpen = false);
   
      //***********************************
      //**********UNIT*********************
      //***********************************
      /**
       * Get All Unit clients of a machine
       *
       * \see UnitClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TUnitClientMap which contains all 
       *                               the pointers and instance names of the machine
       */ 
      TUnitClientMap GetUnitClients(bool aOpen = false);


      /**
       * Get one Unit client of a machine by giving the instance name
       *
       * \see UnitClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Unit client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Unit::CUnitClient *GetUnitClient(std::string aInstanceName, bool aOpen = false);
    
      //***********************************
      //**********WIRELESS*****************
      //***********************************
      /**
       * Get All Wireless clients of a machine
       *
       * \see WirelessClient.hpp
       * \see MachineCtrlTypes.hpp
       *
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * return                        Pointer to TWirelessClientMap which contains all 
       *                               the pointers and instance names of the machine
       */
      TWirelessClientMap GetWirelessClients(bool aOpen = false);


      /**
       * Get one Wireless client of a machine by giving the instance name
       *
       * \see WirelessClient.hpp
       *
       * @param[in] aInstanceName      Instance name of the service
       * @param[in] aOpen              Bool if wanted that the returned client is opened 
       * @return                       Pointer to the Wireless client or NULL if 
       *                               no such instance is available or couldn't open it 
       *                               if wanted
       */
      MaCI::Wireless::CWirelessClient *GetWirelessClient(std::string aInstanceName, bool aOpen = false);
      
    private:
      
      MaCI::CMaCI *GetMaCIPointer(EInterfaceType aType, std::string aInstanceName);
      void ConstructMaCIClient(MaCI::MaCICtrl::SMaCISL aMaCISl,MaCI::MaCICtrl::SServiceEntry aService);
      void ConstructClientMaps();
      void DestructAllClients();



      gimi::GIMI *iGIMI;
      bool iOwnGIMI;
      MaCI::MaCICtrl::CMaCICtrlClient *iMCC;
      std::string iMaCIGroup;
      TMaCIClientsMap iMaCIClients;




      //Private copy constructor and assignment operator
      CMachineCtrlClient (const CMachineCtrlClient &) 
        : iGIMI(NULL),
          iOwnGIMI(false),
          iMCC(NULL),
          iMaCIGroup(""),
          iMaCIClients(){}
      CMachineCtrlClient &operator=(const CMachineCtrlClient &) { return *this; }
    };
  }
}
#endif ///< _MACHINE_CTRL_CLIENT_HPP
